package axht.trade.xposed;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.util.Map;

import android.app.Application;
import android.content.Context;
import android.view.View;
import android.widget.EditText;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;

public class XposedHook implements IXposedHookLoadPackage{

    /**
     * xposed插件入口点
     * */
    @Override
    public void handleLoadPackage(LoadPackageParam pparam)
            throws Throwable {
        // pparam.processName 获取应用程序包名
        // XposedBridge.log("当前启动的应用程序是："+pparam.processName);

        if(pparam.packageName.equals("com.qianyu.zhuceji")){
            //hook 普通方法、静态方法
            XposedHelpers.findAndHookMethod(
                    "com.qianyu.zhuceji.MainActivity", //包名+类名
                    pparam.classLoader,  //类的加载器
                    "checkSN",   		//方法名
                    String.class,		//参数列表
                    String.class,
                    new XC_MethodHook() {
                        /**
                         * HOOK之前
                         * 打印参数信息、修改参数
                         * */
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param)
                                throws Throwable {
                            super.beforeHookedMethod(param);
//							XposedBridge.log("修改之前userName："+param.args[0]);
//							XposedBridge.log("修改之前sn："+param.args[1]);
                            /**
                             * java反射机制
                             * */
                            // 获取类
                            Class<?> clazz=param.thisObject.getClass();
                            //XposedBridge.log("clazz："+clazz);
                            // 获取字段
                            Field sn=clazz.getDeclaredField("edit_sn");
                            // 设置可见
                            sn.setAccessible(true);// 注意
                            EditText et_sn=(EditText) sn.get(param.thisObject);
                            // 打印输出验证码字段
                            XposedBridge.log("sn："+et_sn.getText());

                            String userName=(String)param.args[0];
                            MessageDigest digest = MessageDigest.getInstance("MD5");
                            digest.reset();
                            digest.update(userName.getBytes());

                            // 获取方法
                            Method method=clazz.getDeclaredMethod("toHexString", new Class[]{byte[].class, String.class});
                            // 设置方法为可见
                            method.setAccessible(true);
                            // 调用方法
                            String hexstr=(String) method.invoke(param.thisObject, new Object[]{digest.digest(),""});

                            //主动调用方法
//					        String hexstr = (String) XposedHelpers.callStaticMethod(
//					        		param.thisObject.getClass(), //获取类
//					        		"toHexString",
//					        		new Object[]{digest.digest(),""});

                            StringBuilder sb = new StringBuilder();
                            for (int i = 0; i < hexstr.length(); i += 2) {
                                sb.append(hexstr.charAt(i));
                            }

                            //设置编辑框的内容
                            et_sn.setText(sb.toString());

                            //修改参数
                            //param.args[0]="ke.yijincc.com";
                            //param.args[1]="3192850648@qq.com";
                            //param.args[1]=sb.toString();
                            //XposedBridge.log("修改之后sn："+param.args[1]);
                        }

                        /**
                         * HOOK之后
                         * 打印返回值信息、修改返回值
                         * */
                        @Override
                        protected void afterHookedMethod(MethodHookParam param)
                                throws Throwable {
                            super.afterHookedMethod(param);
                            XposedBridge.log("返回值："+param.getResult());
                            //修改返回值之后
                            //param.setResult(true);
                        }
                    });

            //hook 匿名内部类
            XposedHelpers.findAndHookMethod(
                    "com.qianyu.zhuceji.MainActivity$1",
                    pparam.classLoader,
                    "onClick",
                    View.class,
                    new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param)
                                throws Throwable {
                            super.beforeHookedMethod(param);
                            View view=(View)param.args[0];
                            XposedBridge.log("view："+view.getId());
                        }
                    });
        }

        if(pparam.packageName.equals("com.qianyu.ggactivity")){
            // hook构造方法  不需要填写方法名
            XposedHelpers.findAndHookConstructor(
                    "com.qianyu.ggactivity.Module", //包名+类名
                    pparam.classLoader,
                    int.class,		//参数列表
                    String.class,
                    new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param)
                                throws Throwable {
                            super.beforeHookedMethod(param);
                            //XposedBridge.log("参数1："+param.args[0]);
                            //XposedBridge.log("参数2："+param.args[1]);

                            Class<?> clazz=param.thisObject.getClass();
                            // 获取指定类里面的所有字段
                            Field[] fields=clazz.getDeclaredFields();
                            for (Field field : fields) {
                                XposedBridge.log("字段名称："+field.getName());
                            }

                            // 获取指定类里面的所有方法
                            Method[] methods=clazz.getDeclaredMethods();
                            for (Method method : methods) {
                                XposedBridge.log("方法名称："+method.getName());
                            }

                        }
                    });

            // 遍历所有的类 解决动态加载dex文件hook不到的问题
            XposedHelpers.findAndHookMethod(
                    ClassLoader.class,
                    "loadClass",
                    String.class,
                    new XC_MethodHook() {
                        @Override
                        protected void afterHookedMethod(MethodHookParam param)
                                throws Throwable {
                            super.afterHookedMethod(param);
                            Class<?> clazz=(Class<?>) param.getResult();
                            XposedBridge.log("clazz："+clazz.getName());
                        }
                    });
            //获取普通字段
            //XposedHelpers.getBooleanField(obj, fieldName)
            //获取静态字段
            //XposedHelpers.getStaticBooleanField(clazz, fieldName)
            //主动调用普通方法
            //XposedHelpers.callMethod(obj, methodName, args)
            //主动调用静态方法
            //XposedHelpers.callStaticMethod(clazz, methodName, args)
        }

        if(pparam.packageName.equals("com.yunhaoge.tanchishe.egame")){
            //方法替换
            //获取类
            final Class<?> clazz=XposedHelpers.findClass("com.qy.zombie.zombie", pparam.classLoader);
            XposedHelpers.findAndHookMethod(
                    "com.qy.zombie.zombie$3",
                    pparam.classLoader,
                    "payCancel",
                    Map.class,
                    new XC_MethodReplacement() {

                        @Override
                        protected Object replaceHookedMethod(MethodHookParam arg0) throws Throwable {
                            //XposedBridge.log("方法替换成功");
                            XposedHelpers.callStaticMethod(clazz, "BuySccess");
                            return null;
                        }
                    });
            XposedHelpers.findAndHookMethod(
                    "com.qy.zombie.zombie$3",
                    pparam.classLoader,
                    "payFailed",
                    Map.class,
                    int.class,
                    new XC_MethodReplacement() {

                        @Override
                        protected Object replaceHookedMethod(MethodHookParam arg0) throws Throwable {
                            //XposedBridge.log("方法替换成功");
                            XposedHelpers.callStaticMethod(clazz, "BuySccess");
                            return null;
                        }
                    });

            //hook Application中的attach方法 解决多dex文件中有些类hook不到的问题
            XposedHelpers.findAndHookMethod(
                    Application.class,
                    "attach",
                    Context.class,
                    new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param)
                                throws Throwable {
                            super.beforeHookedMethod(param);
                            Context context=(Context) param.args[0];
                            ClassLoader loader=context.getClassLoader();
                            XposedHelpers.findAndHookMethod(
                                    "com.qy.zombie.zombie$3",
                                    loader,
                                    "payCancel",
                                    Map.class,
                                    new XC_MethodHook() {
                                        @Override
                                        protected void beforeHookedMethod(MethodHookParam param)
                                                throws Throwable {
                                            super.beforeHookedMethod(param);
                                        }
                                    });
                        }
                    });
        }
    }
}

